package com.note.handler;

import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

/**
 * 自定义 Sentinel 网关限流和熔断的异常处理器。
 * 当触发 Sentinel 的流控或熔断规则时，该处理器会捕获异常并返回自定义的响应内容。
 * <p>
 * 该处理器实现了 BlockRequestHandler 接口，覆盖了 handleRequest 方法。
 * 在 handleRequest 方法中，根据异常类型（如 DegradeException 表示熔断，BlockException 表示流控），
 * 构建并返回不同的响应内容，包括状态码、内容类型和响应体。
 * <p>
 * 示例：
 * - 如果是熔断异常，返回状态码 423（Locked）和自定义的 JSON 响应体。
 * - 如果是流控异常，返回状态码 429（Too Many Requests）和自定义的 JSON 响应体。
 * <p>
 * 注意：
 * - 该处理器需要注册为 Spring 的 Bean，以便在 Sentinel 触发异常时被调用。
 *
 * @author yuhuan
 * @date 2025/3/21
 */
public class SentinelFallbackHandler implements BlockRequestHandler {
    @Override
    public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable ex) {
        if (ex instanceof DegradeException) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", 423);
            result.put("msg", "接口被熔断了");
            return ServerResponse.status(HttpStatus.LOCKED)
                    .contentType(MediaType.APPLICATION_JSON)
                    .bodyValue(result);
        }
        Map<String, Object> result = new HashMap<>();
        result.put("code", 429);
        result.put("msg", "接口被限流了");
        return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(result);
    }
}